// 《围棋》作者版权所有。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// 此文件包含一个驱动程序。UI实现
// 如果可能的话，它提供了readline功能。

// go:build（达尔文| |蜻蜓| | | freebsd | | | linux | | netbsd | | openbsd | | solaris | | windows）和&！阿彭金&！android 

package main

import (
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/google/pprof/driver"
	"golang.org/x/term"
)

func init() {
	newUI = newReadlineUI
}

// readlineUI实现驱动程序。用户界面使用
// golang。org/x/term包。
// 上游pprof命令使用github实现相同的功能。com/chzyer/readline包。
type readlineUI struct {
	term *term.Terminal
}

func newReadlineUI() driver.UI {
	// 在dumb terminal中禁用readline UI。（golang.org/issue/26254）
	if v := strings.ToLower(os.Getenv("TERM")); v == "" || v == "dumb" {
		return nil
	}
	// 测试我们是否可以使用这个术语。ReadLine 
	// 假定在原始模式下运行。
	oldState, err := term.MakeRaw(0)
	if err != nil {
		return nil
	}
	term.Restore(0, oldState)

	rw := struct {
		io.Reader
		io.Writer
	}{os.Stdin, os.Stderr}
	return &readlineUI{term: term.NewTerminal(rw, "")}
}

// Read返回从用户处读取的一行文本（命令）。
// 在读取命令之前打印提示符。
func (r *readlineUI) ReadLine(prompt string) (string, error) {
	r.term.SetPrompt(prompt)

	// 跳过错误检查，因为我们在最初创建此readlineUI时对其进行了测试。
	oldState, _ := term.MakeRaw(0)
	defer term.Restore(0, oldState)

	s, err := r.term.ReadLine()
	return s, err
}

// Print向用户显示一条消息。
// 它将文本格式化为fmt。如果尚未打印，则打印并添加最终\n。
// 对于基于行的用户界面，打印写入标准错误。
// （标准输出保留用于报告数据。）
func (r *readlineUI) Print(args ...any) {
	r.print(false, args...)
}

// PrintErr向用户显示一条错误消息。
// 它将文本格式化为fmt。如果尚未打印，则打印并添加最终\n。
// 对于基于行的UI，PrintErr写入标准错误。
func (r *readlineUI) PrintErr(args ...any) {
	r.print(true, args...)
}

func (r *readlineUI) print(withColor bool, args ...any) {
	text := fmt.Sprint(args...)
	if !strings.HasSuffix(text, "\n") {
		text += "\n"
	}
	if withColor {
		text = colorize(text)
	}
	fmt.Fprint(r.term, text)
}

// colorize使用ANSI颜色转义以红色打印消息。
func colorize(msg string) string {
	const red = 31
	var colorEscape = fmt.Sprintf("\033[0;%dm", red)
	var colorResetEscape = "\033[0m"
	return colorEscape + msg + colorResetEscape
}

// IsTerminal报告用户界面是否已知与交互终端绑定（而不是重定向到文件）。
func (r *readlineUI) IsTerminal() bool {
	const stdout = 1
	return term.IsTerminal(stdout)
}

// WantBrowser指示浏览器是否应使用-http选项打开。
func (r *readlineUI) WantBrowser() bool {
	return r.IsTerminal()
}

// SetAutoComplete指示用户界面调用complete（cmd）以获取
// /如果用户界面完全支持自动完成，则自动完成cmd。
func (r *readlineUI) SetAutoComplete(complete func(string) string) {
	// TODO:实现自动完成支持。
}
